package com.gr.experimental.model.impl.distr.operations;

import com.gr.experimental.model.impl.distr.Context;
import com.gr.experimental.model.impl.distr.operators.BinaryOperator;

public class BinaryOperation implements Expression {

	Expression leftExpression;
	Expression rightExpression;
	BinaryOperator operator;
	
	public BinaryOperation(Expression leftExpression,
			Expression rightExpression, BinaryOperator operator) {
		this.leftExpression = leftExpression;
		this.rightExpression = rightExpression;
		this.operator = operator;

		if (!operator.getArgument1Type().
				isAssignableFrom(leftExpression.getValueType())) {
			throw new IllegalArgumentException("LeftExpression should have type " 
					+ operator.getArgument1Type() +  " but has " 
					+ leftExpression.getValueType());
		}
		if (!operator.getArgument2Type().
				isAssignableFrom(rightExpression.getValueType())) {
			throw new IllegalArgumentException("RightExpression should have type " 
					+ operator.getArgument2Type()+  " but has " 
					+ rightExpression.getValueType());
		}
	}

	@Override
	public Object getValue(Context context) throws CalculationException {
		
		Object left = leftExpression.getValue(context);
		Object right = rightExpression.getValue(context);
		
		return operator.op(left, right);
	}

	@Override
	public Class<?> getValueType() {
		return operator.getReturnType();
	}

	public BinaryOperator getOperator() {
		return operator;
	}


}
